#include "TaskDispatcher.h"
#include "Logger.h"
#include "Singleton.h"

using namespace ddserver::utility;
using namespace ddserver::thread;

TaskDispatcher::TaskDispatcher()
{
}

TaskDispatcher::~TaskDispatcher()
{

}

void TaskDispatcher::init(int threads)
{
    Singleton<ThreadPool>::instance()->create(threads);
    start();
}

void TaskDispatcher::assign(Task* task)
{
    log_debug("task dispatcher assign task");
    m_mutex.lock();
    m_tasks.push_back(task);
    m_cond_taskDisptachers.signal();
    m_mutex.unlock();
}

void TaskDispatcher::handle(Task* task)
{
    log_debug("task dispatcher handle task");
    ThreadPool* threadpool = Singleton<ThreadPool>::instance();
    if (threadpool->get_idle_thread_numbers() > 0)
    {
        threadpool->assign(task);
    }
    else 
    {
        m_mutex.lock();
        m_tasks.push_front(task);
        m_mutex.unlock();
        log_debug("all threads are busy");
    } 
}

void TaskDispatcher::run()
{
    log_debug("TaskDispatcher::run(),this=%x",this);
    sigset_t mask;
    if (0 != sigfillset(&mask))
    {
        log_error("thread manager sigfillset failed");
        return ;
    }
    
    if(0 != pthread_sigmask(SIG_SETMASK,&mask,NULL))
    {
        log_error("thread manager pthread_sigmask failed");
        return ;
    }
    
    while(true)
    {
        m_mutex.lock();
        while(m_tasks.empty())
        {
            m_cond_taskDisptachers.wait(&m_mutex);
        }
        log_debug("TaskDispatcher::run() get cond");
        Task* task = m_tasks.front();
        m_tasks.pop_front();
        m_mutex.unlock();
        handle(task);
    }
}